/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.Workspace;

import java.util.ArrayList;
import java.util.Collection;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.validator.ValidatorException;
import managedbean.LoginAdmin.LoginManagerBean;
import merlion.common.entity.AccessRight;
import merlion.common.entity.Staff;
import merlion.common.session.stateless.SystemUserSessionBeanLocal;
import merlion.common.util.Consts;
import merlion.common.util.exception.UpdateFailureException;
import org.primefaces.event.IdleEvent;

/**
 *
 * @author Zhang Ying
 */
@ManagedBean
@SessionScoped
public class WorkspaceManagerBean {

    @EJB
    private SystemUserSessionBeanLocal systemUserManager;
    private Staff currentStaff;
    private String loggedUsername;
    private Collection<Staff> allStaff;
    // for left menu bar
    private Collection<AccessRight> workspaceFunctions;
    private ArrayList<ArrayList<AccessRight>> sortedFunctions;
    private ArrayList<String> keys;
    // paths defined
    private String loginAdminPath = "/LoginAdmin/";
    private String workspacePath = "/Workspace/";
    private String commonPath = "/CommonUtility/";
    private String pageRedirectAttribute = "?faces-redirect=true";
    // login counts
    private int loginCounts;
    private int pwdWrongCounts;
    // for profile edition
    private String newPassword;
    private String oldPassword;

    /** Creates a new instance of WorkspaceManagerBean */
    public WorkspaceManagerBean() {
        workspaceFunctions = null;
        sortedFunctions = null;
        loginCounts = 0;
    }

    // for menu bar page redirection
    public void redirectToProfilePage(ActionEvent event) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(workspacePath, "profile"));
        } catch (Exception ex) {
        }
    }

    public void redirectToAnnView(ActionEvent event) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(commonPath, "viewMyAnns"));
        } catch (Exception ex) {
        }
    }

    public void redirectToSendNewMsg(ActionEvent event) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(commonPath, "sendNewMsg"));
        } catch (Exception ex) {
        }
    }

    public void redirectToViewAllSent(ActionEvent event) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(commonPath, "viewMsgsSent"));
        } catch (Exception ex) {
        }
    }

    public void redirectToViewAllRcved(ActionEvent event) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(commonPath, "viewMsgsRcved"));
        } catch (Exception ex) {
        }
    }

    public void redirectToViewMyJobList(ActionEvent event) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(commonPath, "viewMyJobList"));
        } catch (Exception ex) {
        }
    }
    
    public void redirectToViewMySchedule(ActionEvent event){
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(commonPath, "viewMySchedule"));
        } catch (Exception ex) {
        }
    }

    public void redirectToHomePage(ActionEvent event) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(workspacePath, "home"));
        } catch (Exception ex) {
        }
    }

    public String redirectToLogoutPage() {
        return getRedirectFullPath(loginAdminPath, "logout");
    }

    // for profile page display and edit
    public String redirectToEditMyInfo() {
        return getRedirectPath(workspacePath, "profileEditInfo");
    }

    public String redirectToEditPwd() {
        return getRedirectPath(workspacePath, "profileEditPwd");
    }

    public String redirectToEditProfileImage() {
        return getRedirectPath(workspacePath, "profilePicture");
    }

    public String redirectToProfilePage() {
        return getRedirectPath(workspacePath, "profile");
    }

    public void saveChanges(ActionEvent event) {
        try {
            updateCurrentStaff();
            currentStaff.getSystemUserAccount().setEncryptedPassword(newPassword);
            newPassword = null;
            oldPassword = null;
            systemUserManager.updateCurrentStaffInfo(currentStaff);
            FacesContext.getCurrentInstance().getExternalContext().redirect(getRedirectFullPath(workspacePath, "profile"));
        } catch (UpdateFailureException ex) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage("Unsuccessful", "Updating staff failed."));
        } catch (Exception ex) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage("Unsuccessful", "Redirection to profile failed."));
        }
    }

    // profile page edit
    public void checkUsernameExists(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String usernameInputed = (String) value;
        if (!currentStaff.getSystemUserAccount().getUsername().equals(usernameInputed)
                && systemUserManager.checkUsernameExist(usernameInputed)) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Username exists", "Username exists");
            throw new ValidatorException(message);
        }
    }

    public void validateSamePassword(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        UIInput passwordField = (UIInput) context.getViewRoot().findComponent("form1:pwd");
        if (passwordField == null) {
            throw new IllegalArgumentException(String.format("Unable to find component."));
        }
        String password = (String) passwordField.getValue();
        String confirmPassword = (String) value;
        if (!confirmPassword.equals(password)) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Passwords do not match", "Passwords do not match!");
            throw new ValidatorException(message);
        }
    }

    public void checkEmailExists(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String emailInputed = (String) value;
        if (!currentStaff.getSystemUserAccount().getEmailAddress().equals(emailInputed)
                && systemUserManager.checkEmailExist(emailInputed)) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, Consts.CREATE_ACCOUNT_EMAIL_EXIST, Consts.CREATE_ACCOUNT_EMAIL_EXIST);
            throw new ValidatorException(message);
        }
    }

    public void checkOldPassword(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String oldpwd = (String) value;
        if (!systemUserManager.checkSystemUserAccountMatch(loggedUsername, oldpwd)) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,"Old password is not correct." , "Old password is not correct.");
            throw new ValidatorException(message);
        }
    }

    // for left menu's functions
    private void initWorkspaceFunctions() {
        currentStaff = (Staff) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(LoginManagerBean.AUTH_KEY);
        loggedUsername = currentStaff.getSystemUserAccount().getUsername();
        setWorkspaceFunctions(systemUserManager.getStaffAccessRights(getLoggedUsername()));
    }

    public Collection<AccessRight> getWorkspaceFunctions() {
        initWorkspaceFunctions();
        return workspaceFunctions;
    }

    public void setWorkspaceFunctions(Collection<AccessRight> workspaceFunctions) {
        this.workspaceFunctions = workspaceFunctions;
    }

    public ArrayList<ArrayList<AccessRight>> getSortedFunctions() {
        initWorkspaceFunctions();
        // for debugging purpose
        if (currentStaff == null) {
            System.out.println("current staff in wpb is null");
        }
        keys = new ArrayList<String>();
        ArrayList<ArrayList<AccessRight>> result = new ArrayList<ArrayList<AccessRight>>();
        for (AccessRight ar : workspaceFunctions) {
            String category = ar.getMethodCategory();
            if (!keys.contains(category)) {
                keys.add(category);
                ArrayList<AccessRight> acs = new ArrayList<AccessRight>();
                acs.add(ar);
                result.add(acs);
            } else {
                int index = keys.indexOf(category);
                result.get(index).add(ar);
            }
        }
        setSortedFunctions(result);
        return sortedFunctions;
    }

    // for session out
    public void idleListener(IdleEvent event) {
        System.out.println("session invalid session infalid");
        //invalidate session  
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(LoginManagerBean.AUTH_KEY);
        setLoggedUsername(null);
        setCurrentStaff(null);
        setLoginCounts(0);
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect("/merlion-war/LoginAdmin/logout.xhtml");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // getters and setters
    public Collection<Staff> getAllStaff() {
        allStaff = systemUserManager.getAllStaff();
        return allStaff;
    }

    public void setAllStaff(Collection<Staff> allStaff) {
        this.allStaff = allStaff;
    }

    public Staff getCurrentStaff() {
        return currentStaff;
    }

    public void setCurrentStaff(Staff currentStaff) {
        this.currentStaff = currentStaff;
    }

    public void setSortedFunctions(ArrayList<ArrayList<AccessRight>> sortedFunctions) {
        this.sortedFunctions = sortedFunctions;
    }

    public ArrayList<String> getKeys() {
        return keys;
    }

    public void setKeys(ArrayList<String> keys) {
        this.keys = keys;
    }

    public String getLoggedUsername() {
        return loggedUsername;
    }

    public void setLoggedUsername(String loggedUsername) {
        this.loggedUsername = loggedUsername;
    }

    public int getLoginCounts() {
        return loginCounts;
    }

    public void setLoginCounts(int loginCounts) {
        this.loginCounts = loginCounts;
    }

    public String getOldPassword() {
        return oldPassword;
    }

    public void setOldPassword(String oldPassword) {
        this.oldPassword = oldPassword;
    }

    public void incrementLoginCounts() {
        loginCounts++;
    }

    public void decrementLoginCounts() {
        loginCounts--;
    }

    public int getPwdWrongCounts() {
        return pwdWrongCounts;
    }

    public void setPwdWrongCounts(int pwdWrongCounts) {
        this.pwdWrongCounts = pwdWrongCounts;
    }

    public void incrementWrongCounts() {
        pwdWrongCounts++;
    }

    public void decrementWrongCounts() {
        pwdWrongCounts--;
    }

    public String getNewPassword() {
        return newPassword;
    }

    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;
    }

    // private helper methods
    private String getRedirectPath(String parentPath, String actionPath) {
        return parentPath + actionPath + pageRedirectAttribute;
    }

    private String getRedirectFullPath(String parentPath, String actionPath) {
        String serverName = FacesContext.getCurrentInstance().getExternalContext().getRequestServerName();
        String serverPort = "8080";
        return "http://" + serverName + ":" + serverPort + "/merlion-war" + parentPath + actionPath + ".xhtml";
    }

    // update current staff
    public void updateCurrentStaff() {
        Staff s = systemUserManager.getStaff(getCurrentStaff().getId());
        setCurrentStaff(s);
        setLoggedUsername(s.getSystemUserAccount().getUsername());
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(LoginManagerBean.AUTH_KEY, s);
    }
}
